package com.zhu.websocketdemo.websocket;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhu.websocketdemo.dto.RankItem;
import com.zhu.websocketdemo.pojo.ChatMessage;
import com.zhu.websocketdemo.pojo.GroupMessage;
import com.zhu.websocketdemo.pojo.PrivateMessage;
import com.zhu.websocketdemo.pojo.ResponseMessage;

import com.zhu.websocketdemo.service.IGroupMessage;
import com.zhu.websocketdemo.service.IPrivateMessage;
import com.zhu.websocketdemo.service.impl.MessageRankService;
import com.zhu.websocketdemo.service.impl.OnlineUserService;
import org.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

// WebSocket处理器
@Component
public class SimpleChatHandler extends TextWebSocketHandler {

    private static OnlineUserService onlineUserService;
    private static MessageRankService messageRankService;
    private static MessageBroadcaster broadcaster;


    private static final Set<WebSocketSession> sessions = ConcurrentHashMap.newKeySet();
    private static final Map<String, WebSocketSession> userSessions = new ConcurrentHashMap<>(); // 用户名->Session映射
    private final ObjectMapper objectMapper = new ObjectMapper(); // JSON工具

    @Autowired
    private IGroupMessage groupMessage;
    @Autowired
    private IPrivateMessage privateMessage;

    @Autowired
    public void setServices(OnlineUserService ous,
                            MessageRankService mrs,
                            MessageBroadcaster mb) {
        onlineUserService = ous;
        messageRankService = mrs;
        broadcaster = mb;
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws IOException, JSONException {
        // 从会话属性中获取用户名
        String user = (String) session.getAttributes().get("user");
        if (user == null) {
            closeWithError(session, "未提供用户名");
            return;
        }

        onlineUserService.userLogin(user);
        sessions.add(session);
        userSessions.put(user, session); // 绑定用户和Session
        WebSocketSession sender = userSessions.get(user);
        LocalDateTime timestamp = LocalDateTime.now();
        // 获取历史消息
        getHistoryMessage(user,sender,timestamp);

        sendOnlineUsersUpdate();
        broadcaster.broadcast(objectMapper.writeValueAsString(new ResponseMessage("系统", "欢迎" + user + "加入聊天室","GROUP")));
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException, JSONException {
        String user = (String) session.getAttributes().get("user");
        try {
            LocalDateTime timestamp = LocalDateTime.now();
            ChatMessage chatMessage = objectMapper.readValue(message.getPayload(), ChatMessage.class);
            ResponseMessage response = new ResponseMessage(user,chatMessage.getContent(), chatMessage.getType(),chatMessage.getToUser());
            messageRankService.incrementMessageCount(user);

                // 通过Redis广播消息
                System.out.println("用户消息排名：" + messageRankService.getTopUsers());

                if ("PRIVATE".equals(chatMessage.getType())){
                    WebSocketSession sender = userSessions.get(user);
                    response.setType("PRIVATE_SENT");
                    sender.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                    privateMessage.save(new PrivateMessage(user, chatMessage.getToUser(), chatMessage.getContent(), timestamp));
                    response.setType("PRIVATE");
                } else {
                    groupMessage.save(new GroupMessage(user,chatMessage.getContent(),timestamp));
                }
                broadcaster.broadcast(objectMapper.writeValueAsString(response));
//            }
        } catch (JsonProcessingException e) {
            closeWithError(session, "消息格式错误");
        }
    }


    /**
     * 广播消息
     * @param message 消息内容
     */
    public static void broadcastMessage(String message) {
        sessions.forEach(session -> {
            if (session.isOpen()) {
                try {
                    session.sendMessage(new TextMessage(message));
                } catch (IOException e) {
                    // 日志记录或关闭失效会话
                    try {
                        session.close(CloseStatus.SERVER_ERROR);
                    } catch (IOException ignored) {}
                }
            }
        });
    }

    /**
     * 通过用户名发送私聊消息
     * @param toUser  目标用户名{可以有多个}
     * @param message 消息内容
     */
    public static void privateMessage(String[] toUser, String message){
        Set<WebSocketSession> sessions = ConcurrentHashMap.newKeySet();
        for (int i = 0; i < toUser.length; i++){
            WebSocketSession user = userSessions.get(toUser[i]);
            if (user != null && user.isOpen()) {
                sessions.add(user);
            }else {
                throw new RuntimeException("用户" + toUser[i] + "不在线");
            }
        }
        sessions.forEach(session -> {
            if(session != null && session.isOpen()){
                try {
                    session.sendMessage(new TextMessage(message));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }
    private void sendOnlineUsersUpdate() {
        Set<String> users = onlineUserService.getOnlineUsers();
        broadcaster.broadcast("ONLINE_USERS:" + String.join(",", users));
    }

    public static void sendMessageRank(){
        System.out.println("用户消息排名：" + messageRankService.getTopUsers());
        ObjectMapper objectMapper = new ObjectMapper();
        sessions.forEach(session -> {
            try {
                String s = objectMapper.writeValueAsString(messageRankService.getTopUsers());
                session.sendMessage(new TextMessage("Rank" + s));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    private void closeWithError(WebSocketSession session, String error) {
        try {
            session.close(new CloseStatus(CloseStatus.BAD_DATA.getCode(), error));
        } catch (IOException ignored) {
        }
    }

    /**
     * 获取历史消息
     * @param user 用户名
     * @param sender 会话
     * @param timestamp 时间戳
     */
    private void getHistoryMessage(String user, WebSocketSession sender,LocalDateTime timestamp){
        groupMessage.findAll().forEach(message -> {
            try {
                sender.sendMessage(new TextMessage(objectMapper.writeValueAsString(message)));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        privateMessage.findByFromUser(user).forEach(message -> {
            try {
                ResponseMessage receiverMsg = new ResponseMessage(
                        message.getFromUser(),
                        message.getToUser(),
                        message.getContent(),
                        "PRIVATE_SENT",
                        message.getTimestamp()
                );
                sender.sendMessage(new TextMessage(objectMapper.writeValueAsString(receiverMsg)));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        privateMessage.findByToUser(user).forEach(message -> {
            try {
                ResponseMessage receiverMsg = new ResponseMessage(
                        message.getFromUser(),
                        message.getContent(),
                        "PRIVATE",
                        message.getTimestamp()
                );
                sender.sendMessage(new TextMessage(objectMapper.writeValueAsString(receiverMsg)));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        ResponseMessage receiverMsg = new ResponseMessage(
                "系统",
                "以上是历史聊天记录",
                "PRIVATE",
                timestamp
        );
        try {
            sender.sendMessage(new TextMessage(objectMapper.writeValueAsString(receiverMsg)));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws IOException{
        String user = (String) session.getAttributes().get("user");
        sessions.remove(session);
        userSessions.remove(user); // 移除离线用户
        onlineUserService.userLogout(user);
        broadcaster.broadcast(objectMapper.writeValueAsString(new ResponseMessage("系统",user + "退出了聊天室","GROUP")));
    }
}